#include "vim-h265-live-reader.h"
#include <assert.h>
#include <string.h>
#include <algorithm>
 #include <sys/time.h>

#define H265_NAL(v)	 ((v>> 1) & 0x3f)

enum { NAL_IDR_W_RADL = 19, NAL_IDR_N_LP= 20, NAL_VPS = 32, NAL_SPS = 33, NAL_PPS = 34, NAL_SEI = 39};

static inline unsigned int get_timestamp( struct timeval *stime, struct timeval *stimepre)
{
	gettimeofday(stime,NULL);
    //printf("sec: %ld, usec: %ld\n", stime->tv_sec, stime->tv_usec);
    //printf("sec: %ld, usec: %ld\n", stimepre->tv_sec, stimepre->tv_usec);
    int ret = (stime->tv_usec) * 90 / 1000 - ( stimepre->tv_usec) * 90 / 1000;
    ret = ret > 0 ? ret : (90000 - ((stimepre->tv_usec) * 90 / 1000) + (stime->tv_usec) * 90 / 1000);
    //printf(">>>>>>>>>%d\n", ret);
    memcpy(stimepre, stime, sizeof( struct timeval));
    return ret;
}


H265LiveReader::H265LiveReader(const char* file)
:m_ptr(NULL), m_capacity(0),m_queue(NULL)
{
	printf("new CQueue enter\n");
	m_queue = new CQueue(5, 1920 * 1080);
	//Init();
}

H265LiveReader::~H265LiveReader()
{    
	if (m_queue)
	{
		delete m_queue;
	}
	printf("delete clloc succeed\n");
}

bool H265LiveReader::IsOpened() const
{
	return 1;//!m_videos.empty();
}

int H265LiveReader::reader_send_stream_to_buf(unsigned char *data, int len)
{
	//printf(">>>>>reader_send_stream_to_buf %d \n", len);
	return m_queue->push(data,len);
}


int H265LiveReader::GetNextFrame(int64_t &dts, uint8_t* &ptr, int &bytes)
{
	int ret = 0;
	m_stimestate = get_timestamp(&m_stime, &m_stimepre);
	dts = m_stimestate;
	ret = m_queue->pop(ptr, &bytes);
	
	//printf(">>>>>get nextframe %d \n", bytes);
	return ret;
}

int H265LiveReader::Seek(int64_t &dts)
{

	return 0;
}



static inline const uint8_t* search_start_code(const uint8_t* ptr, const uint8_t* end)
{
    for(const uint8_t *p = ptr; p + 3 < end; p++)
    {
        if(0x00 == p[0] && 0x00 == p[1] && (0x01 == p[2] || (0x00==p[2] && 0x01==p[3])))
            return p;
    }
	return end;
}

static inline int h265_nal_type(const unsigned char* ptr)
{
    int i = 2;
    assert(0x00 == ptr[0] && 0x00 == ptr[1]);
    if(0x00 == ptr[2])
        ++i;
    assert(0x01 == ptr[i]);
    return H265_NAL(ptr[i+1]);
}


int H265LiveReader::Init()
{
	//size_t count = 0;
    bool vpsspspps = true;

	//const uint8_t* end = m_ptr + m_capacity;
    uint8_t* nalu = (uint8_t *)malloc(1920*1080);//search_start_code(m_ptr, end);
	const uint8_t* p = nalu;

	while (1)
	{
        //const unsigned char* pn = search_start_code(p + 4, end);
		int bytes = 0;
		int ret = m_queue->pop(nalu, &bytes);
		if (ret <= 0)
		{
			continue;
		}
		
        int nal_unit_type = h265_nal_type(p);
		assert(0 <= nal_unit_type);

        if(NAL_VPS == nal_unit_type || NAL_SPS == nal_unit_type || NAL_PPS == nal_unit_type)
        {
            if(vpsspspps)
            {
                size_t n = 0x01 == p[2] ? 3 : 4;
				std::pair<const uint8_t*, size_t> pr;
				pr.first = p + n;
				pr.second = bytes;
				m_sps.push_back(pr);
				printf(">>>>>>>>>>>>>>>>ok\n");
				break;
            }
        }
	#if 0	
        {
            if(m_sps.size() > 0) vpsspspps = false; // don't need more vps/sps/pps

			vframe_t frame;
			frame.nalu = nalu;
			frame.bytes = bytes;
			frame.time = 40 * count++;
			frame.idr = (NAL_IDR_N_LP == nal_unit_type || NAL_IDR_W_RADL == nal_unit_type); // IDR-frame
			m_videos.push_back(frame);
			nalu = pn;
        }
	#endif
    }
    return 0;
}
